/*
 *  common.c
 *  FrostOS
 *
 *  Created by bluechill on 12/11/09.
 *  Copyright 2009 SecurityOverride. All rights reserved.
 *
 */

#include <common.h>
#include <ostream.h>
#include <istream.h>

using namespace std;

extern void panic(const char *message, const char *file, uint32_t line)
{
		// We encountered a massive problem and have to stop.
    asm volatile("cli"); // Disable interrupts.
	
	cout << "PANIC(" << message << ") at " << file << ":" << line << "\n";
		// Halt by going into an infinite loop.
    for(;;);
}

extern void panic_assert(const char *file, uint32_t line, const char *desc)
{
		// An assertion failed, and we have to panic.
    asm volatile("cli"); // Disable interrupts.
	
    cout << "ASSERTION-FAILED(" << desc << ") at " << file << ":" << line << "\n";
		// Halt by going into an infinite loop.
    for(;;);
}

	// Copy len bytes from src to dest.
void memcpy(uint8_t *dest, const uint8_t *src, uint32_t len)
{
    const uint8_t *sp = (const uint8_t *)src;
    uint8_t *dp = (uint8_t *)dest;
    for(; len != 0; len--) *dp++ = *sp++;
}

	// Write len copies of val into dest.
void memset(uint8_t *dest, uint8_t val, uint32_t len)
{
    uint8_t *temp = (uint8_t *)dest;
    for ( ; len != 0; len--) *temp++ = val;
}

	// Compare two strings. Should return -1 if 
	// str1 < str2, 0 if they are equal or 1 otherwise.
int strcmp(char *str1, char *str2)
{
	int i = 0;
	int failed = 0;
	while(str1[i] != '\0' && str2[i] != '\0')
	{
		if(str1[i] != str2[i])
		{
			failed = 1;
			break;
		}
		i++;
	}
		// why did the loop exit?
	if( (str1[i] == '\0' && str2[i] != '\0') || (str1[i] != '\0' && str2[i] == '\0') )
		failed = 1;
	
	return failed;
}

	// Copy the NULL-terminated string src into dest, and
	// return dest.
char *strcpy(char *dest, const char *src)
{
    do
    {
		*dest++ = *src++;
    }
    while (*src != 0);
	return dest;
}

	// Concatenate the NULL-terminated string src onto
	// the end of dest, and return dest.
char *strcat(char *dest, const char *src)
{
	while (*dest != 0)
    {
        *dest++;
    }
	
    do
    {
        *dest++ = *src++;
    }
    while (*src != 0);
    return dest;
}

	//compares two peices of memory
char memcmp(const void *_m1, const void *_m2, unsigned short n)
{
	unsigned char *m1 = (unsigned char *)_m1, *m2 = (unsigned char *)_m2;
	unsigned short i;
	
	for(i=0; i<n; i++)
	{
		if(m1[i] != m2[i])
		{
			return (m1[i] > m2[i] ? 1 : -1);
		}
	}
	return 0;
}

	//copies a peice of memory to a new location
void memcpy(void *_d, void *_s, unsigned short n)
{
	unsigned char *d = (unsigned char *)_d, *s = (unsigned char *)_s;
	unsigned short i;
	
	for(i=0; i<n; i++)
	{
		d[i] = s[i];
	}
}

	//calculates the length of a string (including '\0')
size_t strlen(char *s)
{
	size_t len = 0;
	
	for (;*s != '\0';*s++)
	{
		len++;
	}
	
	return len;
}

	//Converts a number to a base 10 digit (requires replacement)
void ntostr(unsigned int i, char *s)
{
	unsigned char backstr[21], j=0, l=0, m=0;
	
	do							// Convert string one digit at a time
	{
		backstr[j++] = (i % 10) + '0';	//Put a digit in backstr
		i /= 10;							//get next digit
	}
	while(i);
	
	backstr[j] = '\0';			//End of the string
	
	for(l=j-1; m<j; l--)			//Backstr is backwards
	{							// Now we flip it
		s[m++] = backstr[l];
	}
	
	s[j] = '\0';
}

unsigned char* memset(unsigned char *dest, unsigned char val, int count)
{
    /* Add code here to set 'count' bytes in 'dest' to 'val'.
	 *  Again, return 'dest' */
	for (int i=0;i<count;i++)
	{
		dest[i] = val;
	}
	return dest;
}

unsigned short* memsetw(unsigned short *dest, unsigned short val, int count)
{
    /* Same as above, but this time, we're working with a 16-bit
	 *  'val' and dest pointer. Your code can be an exact copy of
	 *  the above, provided that your local variables if any, are
	 *  unsigned short */
	for (int i=0;i<count;i++)
	{
		dest[i] = val;
	}
	return dest;
}
